﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace GameLogic.Logic
{
    public class FollowMouseBehavior : GameContainerBehavior<FrameworkElement>
    {
        #region Dependency properties
        [Category("FollowMouse Properties")]
        public PositionOptions FollowPosition
        {
            get { return (PositionOptions)this.GetValue(FollowPositionProperty); }
            set { this.SetValue(FollowPositionProperty, value); }
        }
        public static readonly DependencyProperty FollowPositionProperty =
          DependencyProperty.Register(
              "FollowPosition",
              typeof(PositionOptions),
              typeof(FollowMouseBehavior),
              new PropertyMetadata(PositionOptions.XY, null));

        public enum PositionOptions
        {
            None,
            X,
            Y,
            XY
        };
        #endregion

        bool followMouse;
        Point center;
        Rect startPosition;
        Rect worldLimit;
        
        protected override void OnAttached()
        {
            base.OnAttached();

        }

        protected override void OnGameContainerInitialized()
        {
            base.OnGameContainerInitialized();

            this.center = new Point(this.AssociatedObject.ActualWidth / 2, this.AssociatedObject.ActualHeight / 2);

            UIElement root = this.GameContainer as UIElement;
            Point position = this.AssociatedObject.TransformToVisual(root).Transform(new Point(0,0));
            this.startPosition = new Rect(
                position.X - this.center.X,
                position.Y - this.center.Y,
                this.AssociatedObject.ActualWidth, 
                this.AssociatedObject.ActualHeight);

            Vector2D gcv = new Vector2D(this.GameContainer.GameControl.ActualWidth, this.GameContainer.GameControl.ActualHeight);
            double gcvo = gcv.Length / 2;

            Vector2D gv = new Vector2D(this.GameContainer.ActualWidth, this.GameContainer.ActualHeight);
            double gvo = gcv.Length / 2;

            this.worldLimit = new Rect(
                gcvo - gvo,
                gcvo - gvo,
                this.GameContainer.GameControl.ActualWidth - this.AssociatedObject.ActualWidth,
                this.GameContainer.GameControl.ActualHeight - this.AssociatedObject.ActualHeight);
              
            this.GameContainer.GameControl.MouseEnter += new MouseEventHandler(OnMouseEnter);
            this.GameContainer.GameControl.MouseLeave += new MouseEventHandler(OnMouseLeave);
            this.GameContainer.GameControl.MouseMove += new MouseEventHandler(OnMouseMove);
        }

        private void OnMouseEnter(object sender, MouseEventArgs e)
        {
            followMouse = true;
        }

        private void OnMouseLeave(object sender, MouseEventArgs e)
        {
            followMouse = false;
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (followMouse && this.FollowPosition != PositionOptions.None)
            {
                UIElement root = this.GameContainer as UIElement;
                Point mousePos = e.GetPosition(this.GameContainer.GameControl);
                Point targetPos = new Point(0, 0);

                switch (this.FollowPosition)
                {
                    case PositionOptions.X:
                        targetPos.X = mousePos.X - this.center.X;
                        break;

                    case PositionOptions.Y:
                        targetPos.Y = mousePos.Y - this.center.Y;
                        break;

                    case PositionOptions.XY:
                        targetPos.X = mousePos.X - this.center.X;
                        targetPos.Y = mousePos.Y - this.center.Y;
                        break;
                }

                if (targetPos.X < worldLimit.X)
                    targetPos.X = worldLimit.X;

                if (targetPos.X > worldLimit.Width)
                    targetPos.X = worldLimit.Width;

                if (targetPos.Y < worldLimit.Y)
                    targetPos.Y = worldLimit.Y;

                if (targetPos.Y > worldLimit.Height)
                    targetPos.Y = worldLimit.Height;

                Rect newPos = new Rect(
                targetPos.X,
                targetPos.Y,
                this.AssociatedObject.ActualWidth,
                this.AssociatedObject.Height);
                this.AssociatedObject.Arrange(newPos);
            }
        }

        private void OnGameContainer_Reset(object sender, EventArgs e)
        {
            this.AssociatedObject.Arrange(this.startPosition);
        }
    }
}
